/* =============================================================
 * Your Grandmother's guide to Algorithms
 * =============================================================
 *
 * Copyright (c) 2007, Saverio Miroddi
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * 
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright 
 *       notice, this list of conditions and the following disclaimer in the 
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the SaverioMiroddiSoftware nor the names of its 
 *       contributors may be used to endorse or promote products derived from 
 *       this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *  
 * ---------------------------
 * SortMergeAlgo.java
 * ---------------------------
 *
 */
package algos;

import utils.Utils;
import dbobjects.Condition;
import dbobjects.tables.OrderedTable;
import dbobjects.tables.Table;

/**
 * Quite different from others, so it doesn't make use of superclass' loop
 * methods.
 * 
 * @author Saverio Miroddi
 */
class SortMergeAlgo extends AbstractAlgo {	
	SortMergeAlgo(Table leftTable, Table rightTable, Condition cond, int type) {
		super(leftTable, rightTable, cond, type);
		
		assert (cond.operator != Condition.OP_NE && cond.operator != Condition.OP_EQ);
		
		orderTables();

		leftTable.beforeFirst();
		rightTable.beforeFirst();
	}
	
	/**
	 * Replace tables with ordered ones; needed for the algorithm.
	 */
	private void orderTables() {
		int leftOrderPos = cond.leftPos;
		this.leftTable = new OrderedTable(leftTable, leftOrderPos, false);		

		/*
		 * to simplify the merging algorithm, for some cases we reverse the
		 * order of the right table, to always use forward iteration
		 */ 
		
		int rightOrderPos = cond.rightPos;
		
		if (cond.operator == Condition.OP_B) {
			this.rightTable = new OrderedTable(rightTable, rightOrderPos, true);		
		}
		else if (cond.operator == Condition.OP_BE) {
			this.rightTable = new OrderedTable(rightTable, rightOrderPos, true);		
		}
		else {
			this.rightTable = new OrderedTable(rightTable, rightOrderPos, false);		
		}		
	}

	@Override
	public boolean next() {
		while (leftOuterLoop()) {
			String[] leftRow = leftTable.getRow();

			while (rightInnerLoop()) {
				String[] rightRow = rightTable.getRow();

				if (cond.isTrue(leftRow, rightRow)) {
					foundRightRow = true;
					currRow = Utils.merge(leftRow, rightRow);
					return true;
				}
				else {
					// remaining records aren't useful. reset table
					// and do another outer loop
					advanceLeft = true;
					break;
				}
			}

			if (type == Join.LEFT_OUTER && ! foundRightRow) {
				String[] rightRow = rightTable.getNullRow();
				currRow = Utils.merge(leftRow, rightRow);
				return true;
			}
		}

		return false;
	}
}
